package com.ruoyi.app.business.account;

import cn.hutool.core.collection.CollUtil;
import com.ruoyi.app.config.util.UserUtil;
import com.ruoyi.app.converter.LaborAccountConverter;
import com.ruoyi.app.domain.account.AccountWithdraw;
import com.ruoyi.app.domain.account.LaborAccount;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.CommonUtils;
import com.ruoyi.common.core.utils.PageUtils;
import com.ruoyi.common.core.web.page.CommonPageInfo;
import com.ruoyi.service.account.entity.LaborAccountDetailEntity;
import com.ruoyi.service.account.entity.LaborAccountEntity;
import com.ruoyi.service.account.enums.labor.LaborAccountChangeTypeEnum;
import com.ruoyi.service.account.query.LaborAccountQuery;
import com.ruoyi.service.account.service.LaborAccountDetailService;
import com.ruoyi.service.account.service.LaborAccountService;
import com.ruoyi.service.project.entity.ProjectEntity;
import com.ruoyi.service.project.entity.ProjectLaborEntity;
import com.ruoyi.service.project.entity.ProjectSettleDetailEntity;
import com.ruoyi.service.project.entity.ProjectSettleEntity;
import com.ruoyi.service.project.enums.SettleTypeEnum;
import com.ruoyi.service.project.service.ProjectService;
import com.ruoyi.service.reward.entity.LaborRewardEntity;
import com.ruoyi.service.reward.enums.RewardTypeEnum;
import com.ruoyi.service.user.entity.UserEntity;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 作用：员工账户管理
 * </p>
 *
 * @author Zane
 * @since 2025-10-19 9:08
 */
@Component
public class LaborAccountBusiness {

  @Resource
  private LaborAccountService laborAccountService;
  @Resource
  private LaborAccountDetailService laborAccountDetailService;

  @Resource
  private ProjectService projectService;

  @Transactional(rollbackFor = Exception.class)
  public void settle(ProjectSettleEntity settle, List<ProjectSettleDetailEntity> settleDetails) {
    final List<ProjectSettleDetailEntity> laborSalaries = settleDetails.stream()
        .filter(detail -> SettleTypeEnum.SALARY.eqCode(detail.getSettleType()))
        .collect(Collectors.toList());
    if (CollUtil.isEmpty(laborSalaries)) {
      return;
    }
    final List<Long> laborIds = laborSalaries.stream().map(ProjectSettleDetailEntity::getTargetId)
        .collect(Collectors.toList());
    final Map<Long, LaborAccountEntity> laborAccountMap = laborAccountService.getMapByLaborIds(
        laborIds);
    List<LaborAccountEntity> updateList = new ArrayList<>();
    List<LaborAccountDetailEntity> saveList = new ArrayList<>();
    laborSalaries.forEach(detail -> {
      final LaborAccountEntity laborAccount = CommonUtils.requireNotNull(
          laborAccountMap.get(detail.getTargetId()), "员工账户异常,请联系管理员");
      laborAccount
          .setTotalAmount(laborAccount.getTotalAmount().add(detail.getSettleAmount()))
          .setAmount(laborAccount.getAmount().add(detail.getSettleAmount()))
          .setUpdateBy(settle.getUpdateBy())
          .setUpdateTime(settle.getUpdateTime());
      updateList.add(laborAccount);
      //构建收支明细
      saveList.add(buildAccountDetail(settle, detail, LaborAccountChangeTypeEnum.XZ));
    });
    laborAccountService.updateBatchById(updateList);
    laborAccountDetailService.saveBatch(saveList);
  }

  @Transactional(rollbackFor = Exception.class)
  public void reward(ProjectLaborEntity laborEntity, LaborRewardEntity rewardEntity) {
    final LaborAccountEntity laborAccount = CommonUtils.requireNotNull(
        laborAccountService.getById(laborEntity.getId()), "员工账户异常,请联系管理员");
    final RewardTypeEnum rewardTypeEnum = RewardTypeEnum.valueOfCode(rewardEntity.getChangeType());
    if (RewardTypeEnum.JL == rewardTypeEnum) {
      laborAccount
          .setTotalAmount(laborAccount.getTotalAmount().add(rewardEntity.getAmount()))
          .setAmount(laborAccount.getAmount().add(rewardEntity.getAmount()))
          .setUpdateBy(rewardEntity.getUpdateBy())
          .setUpdateTime(rewardEntity.getUpdateTime());
      laborAccountService.updateById(laborAccount);
      laborAccountDetailService.save(
          buildAccountDetailReward(rewardEntity, LaborAccountChangeTypeEnum.JL));
      return;
    }
    if (RewardTypeEnum.CF == rewardTypeEnum) {
      laborAccount
          .setTotalAmount(laborAccount.getTotalAmount().subtract(rewardEntity.getAmount()))
          .setAmount(laborAccount.getAmount().subtract(rewardEntity.getAmount()))
          .setUpdateBy(rewardEntity.getUpdateBy())
          .setUpdateTime(rewardEntity.getUpdateTime());
      laborAccountService.updateById(laborAccount);
      laborAccountDetailService.save(
          buildAccountDetailReward(rewardEntity, LaborAccountChangeTypeEnum.CF));
      return;
    }

  }

  private LaborAccountDetailEntity buildAccountDetail(ProjectSettleEntity settle,
      ProjectSettleDetailEntity settleDetail,
      LaborAccountChangeTypeEnum changeTypeEnum) {
    //String changeComment = buildChangeComment(settleDetail, changeTypeEnum);
    return new LaborAccountDetailEntity()
        .setLaborId(settleDetail.getTargetId())
        .setProjectId(settleDetail.getProjectId())
        .setProjectName(settleDetail.getProjectName())
        .setPostName(settleDetail.getPostName())
        .setAmount(settleDetail.getSettleAmount())
        .setIoFlag(changeTypeEnum.getIoFlag().getCode())
        .setChangeType(changeTypeEnum.getCode())
        .setChangeTypeName(changeTypeEnum.getName())
        .setChangeComment(changeTypeEnum.getDesc())
        .setTraceKey(String.valueOf(settleDetail.getId()))
        .setCreateBy(settle.getUpdateBy())
        .setCreateTime(LocalDateTime.now())
        .setUpdateBy(settle.getUpdateBy())
        .setUpdateTime(LocalDateTime.now())
        ;
  }

  private LaborAccountDetailEntity buildAccountDetailReward(LaborRewardEntity rewardEntity,
      LaborAccountChangeTypeEnum changeTypeEnum) {
    //String changeComment = buildChangeComment(settleDetail, changeTypeEnum);
    return new LaborAccountDetailEntity()
        .setLaborId(rewardEntity.getLaborId())
        .setProjectId(rewardEntity.getProjectId())
        .setProjectName(rewardEntity.getProjectName())
        .setPostName(rewardEntity.getPostName())
        .setAmount(rewardEntity.getAmount())
        .setIoFlag(changeTypeEnum.getIoFlag().getCode())
        .setChangeType(changeTypeEnum.getCode())
        .setChangeTypeName(changeTypeEnum.getName())
        .setChangeComment(changeTypeEnum.getDesc())
        .setTraceKey(String.valueOf(rewardEntity.getId()))
        .setCreateBy(rewardEntity.getUpdateBy())
        .setCreateTime(LocalDateTime.now())
        .setUpdateBy(rewardEntity.getUpdateBy())
        .setUpdateTime(LocalDateTime.now())
        ;
  }

  private LaborAccountDetailEntity buildAccountDetailWithdraw(AccountWithdraw withdraw) {
    LaborAccountChangeTypeEnum changeTypeEnum = LaborAccountChangeTypeEnum.TX;
    //String changeComment = buildChangeComment(settleDetail, changeTypeEnum);
    return new LaborAccountDetailEntity()
        .setLaborId(UserUtil.getUserId())
        .setProjectId("")
        .setProjectName("")
        .setPostName("")
        .setAmount(withdraw.getAmount())
        .setIoFlag(changeTypeEnum.getIoFlag().getCode())
        .setChangeType(changeTypeEnum.getCode())
        .setChangeTypeName(changeTypeEnum.getName())
        .setChangeComment(changeTypeEnum.getDesc())
        .setTraceKey("")
        .setCreateBy(UserUtil.getUserId())
        .setCreateTime(LocalDateTime.now())
        .setUpdateBy(UserUtil.getUserId())
        .setUpdateTime(LocalDateTime.now())
        ;
  }

  public LaborAccountEntity getByUserId(Long userId) {
    return laborAccountService.getByUserId(userId);
  }

  /**
   * 初始话员工账户
   */
  public void initLaborAccount(UserEntity userEntity) {
    LaborAccountEntity laborAccountEntity = new LaborAccountEntity()
        .setLaborId(userEntity.getUserId())
        .setTotalAmount(BigDecimal.ZERO)
        .setAmount(BigDecimal.ZERO)
        .setCreateBy(userEntity.getUserId())
        .setCreateTime(LocalDateTime.now())
        .setUpdateBy(userEntity.getUserId())
        .setUpdateTime(LocalDateTime.now());
    laborAccountService.save(laborAccountEntity);
  }

  public CommonPageInfo<LaborAccount> accountList(LaborAccountQuery query) {
    final CommonPageInfo<LaborAccountDetailEntity> page = PageUtils.startPage(query);
    page.initData(laborAccountDetailService.accountList(query, UserUtil.getUserId()));
    final CommonPageInfo<LaborAccount> result = page.convert(
        LaborAccountConverter.INSTANCE::toSimple);
    if (CollUtil.isNotEmpty(result.getList())) {
      //补充项目名称
      final List<String> projectIds = result.getList().stream().map(LaborAccount::getTraceKey)
          .distinct().collect(Collectors.toList());
      final Map<String, ProjectEntity> projectMap = projectService.selectMapByIds(
          projectIds);
      result.getList().forEach(item -> {
        final ProjectEntity project = projectMap.get(item.getTraceKey());
        if (project != null) {
          item.setProjectName(project.getProjectName());
        }
      });
    }
    return result;
  }

  @Transactional(rollbackFor = Exception.class)
  public void withdraw(AccountWithdraw withdraw) {
    final LaborAccountEntity laborAccount = laborAccountService.getByUserId(UserUtil.getUserId());
    if (laborAccount.getAmount().compareTo(withdraw.getAmount()) < 0) {
      throw new ServiceException("员工账户余额不足");
    }
    final LaborAccountDetailEntity laborAccountDetailEntity = buildAccountDetailWithdraw(withdraw);
    laborAccount.setAmount(laborAccount.getAmount().subtract(withdraw.getAmount()))
        .setUpdateBy(UserUtil.getUserId())
        .setUpdateTime(LocalDateTime.now());
    laborAccountDetailService.save(laborAccountDetailEntity);
    laborAccountService.updateById(laborAccount);
  }
}

//  private String buildChangeComment(ProjectSettleDetailEntity settleDetail,
//      LaborAccountChangeTypeEnum changeTypeEnum) {
//    settleDetail.getTargetInfo();
//    switch (changeTypeEnum) {
//      case XZ: {
//        new SalaryModel().setProjectId(settleDetail.getProjectId())
//            .setPostName(settleDetail.getPostName())
//            .setPostLevel(settleDetail.getPostLevel())
//            .setProjectName(settleDetail.getProjectName());
//      }
//      case JL:
//      case CF:
//        return "项目处罚";
//      default:
//        throw new IllegalArgumentException("不支持的员工账户变更类型");
//    }
//  }
//}
